package com.irdstudio.efp.esb.api.rest.yx;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import com.irdstudio.efp.esb.api.common.GroupeInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.constant.BaseConstant;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.DateTool;
import com.irdstudio.basic.framework.core.util.DateUtility;
import com.irdstudio.basic.framework.core.util.MessageRuleCheckUtil;
import com.irdstudio.basic.framework.core.util.TraceUtil;
import com.irdstudio.efp.console.common.ConsoleConstant;
import com.irdstudio.efp.esb.api.bean.yx.ReqBraRecoverBean;
import com.irdstudio.efp.esb.api.bean.yx.RespBraRecoverBean;
import com.irdstudio.efp.esb.api.common.EsbRespServiceBeanCreator;
import com.irdstudio.efp.esb.common.constant.EsbBizEnums;
import com.irdstudio.efp.esb.common.constant.EsbSysHeadEnums;
import com.irdstudio.efp.esb.common.constant.nls.NlsProdCdEnum;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.esb.common.server.resp.EsbRespServiceBean;
import com.irdstudio.efp.limit.service.facade.LmtPrdContService;
import com.irdstudio.efp.limit.service.vo.LmtPrdContVO;
import com.irdstudio.efp.loan.service.facade.AccLoanService;
import com.irdstudio.efp.loan.service.vo.AccLoanVO;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.facade.ed.LmtRecoverRecordService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;
import com.irdstudio.efp.nls.service.vo.ed.LmtRecoverRecordVO;
import com.irdstudio.efp.nls.service.vo.sx.NlsCreditInfoVO;

/**
 * 额度恢复接口
  * @author heyingfeng
  * @since 2019年3月13日 下午6:58:41
  * @version 1.0
 */
@RestController
@RequestMapping("/esb")
public class BraRecoverController {
	private static Logger logger = LoggerFactory.getLogger(BraRecoverController.class);

	/**
	 * 获取ESB请求对象，校验 ESB请求系统头和请求应用头对象
	 * 
	 * @param request
	 *            请求对象集合
	 * @return
	 * @author huangwb
	 * @since 2019年1月20日 下午1:28:08
	 * @version 1.0
	 */
	@ModelAttribute("esbReqServiceBean")
	public EsbReqServiceBean getReqEsbHeadBean(HttpServletRequest request) {
		logger.info("校验 ESB请求系统头和请求应用头对象!");
		EsbReqServiceBean esbReqServiceBean = (EsbReqServiceBean) request.getAttribute("esbReqServiceBean");
		return esbReqServiceBean;
	}

	/**
	 * 获取ESB请求对象，校验 ESB请求体对象
	 * 
	 * @param request
	 *            请求对象集合
	 * @return
	 * @author huangwb
	 * @since 2019年1月20日 下午1:31:14
	 * @version 1.0
	 */
	@ModelAttribute("reqBraRecoverBean")
	public ReqBraRecoverBean getReqEsbBodyBean(HttpServletRequest request) {
		logger.info("校验 ESB请求体对象！");
		String esbReqBody = (String) request.getAttribute("esbReqBody");
		return JSONObject.parseObject(esbReqBody, ReqBraRecoverBean.class);
	}

	/**
	 * 1.通过切面校验进件申请参数是否正确，如不正确则返回错误信息<br>
	 * 2.调用对应的中台服务<br>
	 * 3.增加调用队列任务表信息<br>
	 * TODO:此处为统一的进件交易，先暂时不按照产品代码进行划分，后续根据差异化需求决定是否拆分；
	 * 
	 * @param esbReqServiceBean
	 *            ESB请求对象
	 * @param br1
	 * @param reqCreditBean
	 *            ESB请求体的对象
	 * @param br2
	 * @param exception
	 *            切面的异常信息
	 * @return
	 * @throws Exception
	 * @author huangwb
	 * @since 2019年1月20日 下午2:20:51
	 * @version 1.0
	 */
	@PostMapping("/SERVICE_30220010_02")
	public EsbRespServiceBean doRecv(@Validated @ModelAttribute("esbReqServiceBean") EsbReqServiceBean esbReqServiceBean, BindingResult br1,
									 @Validated({GroupeInterface.bd.class}) @ModelAttribute("reqBraRecoverBean") ReqBraRecoverBean reqBraRecoverBean, BindingResult br2, Exception exception) throws Exception {
		// TODO  LmtRecoverSeq是否为LoanOrdrNo  百度报文seq_no
		String applySeq = reqBraRecoverBean.getAppFlowNo();//流水号
		String channelNo = reqBraRecoverBean.getChanFlg();//渠道
		String dblNo = reqBraRecoverBean.getDblNo();//借据号
		String glblSrlNo = esbReqServiceBean.getSysHead().getGlblSrlNo();
		TraceUtil.setTraceId(glblSrlNo);
		logger.info("用信查询开始----------查询流水号：" + applySeq + "------------全局流水号" + glblSrlNo);
		try {
			// 通过切面校验进件申请参数是否正确，如不正确则返回错误信息
			if (Objects.nonNull(exception)) {
				throw exception;
			}
			
			//MessageRuleCheckUtil.checkNumeric(reqBraRecoverBean.getAcctDt(), "账务日期");
			MessageRuleCheckUtil.checkNumeric(reqBraRecoverBean.getTransTm(), "交易时间 ");
			MessageRuleCheckUtil.checkDouble(reqBraRecoverBean.getRpyPrinAmt(), "还款本金金额");

			// MessageRuleCheckUtil.checkDate("账务日期", reqBraRecoverBean.getAcctDt(), "YYYY-MM-DD");
			//MessageRuleCheckUtil.checkDate("交易时间", reqBraRecoverBean.getTransTm(), "yyyyMMddHHmmss");

			// 交易时间转换
			long txnTmstmp = Long.parseLong(reqBraRecoverBean.getTransTm());
			String tranTime = DateTool.formateDate(new Date(txnTmstmp),DateTool.PATTERN_DEFAULT);
			
			LmtRecoverRecordVO lmtRecoverRecordVo = new LmtRecoverRecordVO();
			lmtRecoverRecordVo.setLmtRecoverSeq(applySeq);
			lmtRecoverRecordVo = lmtRecoverRecordService.queryByPk(lmtRecoverRecordVo);
			if (lmtRecoverRecordVo != null) {
				return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean, //
						JSON.toJSONString(buildRespCreditBean(EsbBizEnums.RetCodeEnum.YWLJCLYC.getVALUE(),
								"额度恢复流水号：" + "【" + applySeq + "】" + "，已经存在记录，请核查！")), //
						EsbSysHeadEnums.RetStEnum.FAILURE.getCode(), //
						EsbBizEnums.RetCodeEnum.YWLJCLYC.getVALUE(), //
						"额度恢复流水号：" + "【" + applySeq + "】" + "，已经存在记录，请核查！");
			}

			NlsApplyInfoVO nlsApplyInfoVo = new NlsApplyInfoVO();
			nlsApplyInfoVo.setBdOrderId(reqBraRecoverBean.getDistrOrdrNo());
			nlsApplyInfoVo = nlsApplyInfoService.queryByPk(nlsApplyInfoVo);
			if (nlsApplyInfoVo == null || "".equals(nlsApplyInfoVo.getApplySeq())) {
				nlsApplyInfoVo = new NlsApplyInfoVO();
			}
//			String lmtApplySeq = nlsApplyInfoVo.getLmtApplySeq();//授信流水号

			AccLoanVO accLoanVo = new AccLoanVO();
			accLoanVo.setBillNo(dblNo);
			accLoanVo = accLoanService.queryByPk(accLoanVo);
			if (accLoanVo == null || "".equals(accLoanVo.getLoanBalance()+"")) {
				throw new BizException("无借据数据");
			}
			BigDecimal loanBalance = accLoanVo.getLoanBalance();//上次借据余额

			/*BigDecimal amt = accLoanVo.getLoanAmount().subtract(accLoanVo.getLoanBalance());
			if( new BigDecimal(reqBraRecoverBean.getRpyPrinAmt()).compareTo(amt) != -1 ){
				throw new BizException("还款金额错误");
			}*/

//			LmtPrdContVO lmtPrdContVo = new LmtPrdContVO();
//			lmtPrdContVo.setLmtApplySeq(lmtApplySeq);
//			if(NlsProdCdEnum.MYD.getValue().equals(nlsApplyInfoVo.getPrdCode())){//满易贷   查询额度状态
//				lmtPrdContVo.setLmtStatus(ConsoleConstant.LIMIT_STS_02);
//			}
//			lmtPrdContVo = lmtPrdContService.queryByPk(lmtPrdContVo);
//			if (lmtPrdContVo == null) {
//				throw new BizException("无额度数据");
//			}
			BigDecimal rpyPrinAmt = new BigDecimal(reqBraRecoverBean.getRpyPrinAmt()); //归还金额
//			BigDecimal preOccAmt = lmtPrdContVo.getPreOccAmt();//上次预占用
//			BigDecimal occAmt = lmtPrdContVo.getOccAmt();//上次已用
//			BigDecimal lmtAmt = lmtPrdContVo.getLmtAmt();//授信额度
//			BigDecimal applyAmt = nlsApplyInfoVo.getApplyAmt();//申请金额
//			if(rpyPrinAmt.compareTo(lmtAmt)==1 || rpyPrinAmt.compareTo(loanBalance)==1) {
//				throw new BizException("归还金额本金大于授信额度或大于借据额度");
//			}
			int num = 0;
			// TODO nlsApplyInfoVo判断状态
			if("05".equals(channelNo)) {//度小满
				LmtRecoverRecordVO LmtRecoverRecordVo = new LmtRecoverRecordVO();
				/** 流水号 */
				LmtRecoverRecordVo.setLmtRecoverSeq(applySeq);
				/** 用信申请流水号 */
				LmtRecoverRecordVo.setLmtApplySeq(nlsApplyInfoVo.getApplySeq());
				/** 账务日期 */
				LmtRecoverRecordVo.setAccDate(DateUtility.format8To10(reqBraRecoverBean.getAcctDt()));
				LmtRecoverRecordVo.setAccDate(reqBraRecoverBean.getAcctDt());

				/** 额度恢复类型  */
				LmtRecoverRecordVo.setRecoverType(reqBraRecoverBean.getLmtRcvrTp());
				/** 交易时间 */
				LmtRecoverRecordVo.setTranTime(tranTime);
				/** 恢复金额 */
				LmtRecoverRecordVo.setRecoverAmt(reqBraRecoverBean.getRpyPrinAmt());
				/** 渠道号 */
				LmtRecoverRecordVo.setChannelNo(reqBraRecoverBean.getChanFlg());
				/** 恢复前额度 */
//				LmtRecoverRecordVo.setRecoverBefAmt(lmtPrdContVo.getAvailAmt()+"");
				/** 恢复后额度 */
//				LmtRecoverRecordVo.setRecoverLatAmt(lmtPrdContVo.getAvailAmt()+"");
				/** 创建人 */
				LmtRecoverRecordVo.setCreateUser("admin");
				/** 创建时间 */
				LmtRecoverRecordVo.setCreateTime(DateUtility.getCurrAppDateTimeString());
				/** 恢复场景(0：实时  1：批量) */
				LmtRecoverRecordVo.setScene(BaseConstant.SCENE_0);
				if(BaseConstant.RECOVER_1.equals(reqBraRecoverBean.getLmtRcvrTp()) || 
						BaseConstant.RECOVER_2.equals(reqBraRecoverBean.getLmtRcvrTp())) {//部分还款 借据结清  
					//更新借据表 恢复额度
					//1、额度更新。预占用额度=上一次预占用额度；已占用额度=上一次已占用额度-客户归还本金金额。可用额度=授信额度-预占用-已占用。
					//2、更新借据余额。借据余额=上次借据余额-客户本次归还本金金额。
					//注：网贷只做额度和借据余额的更新，不做还款流水等信息更新，还款流水以批量对账文件为准进行更新。
//					lmtPrdContVo.setPreOccAmt(preOccAmt);
//					lmtPrdContVo.setOccAmt(occAmt.subtract(rpyPrinAmt));
//					if(NlsProdCdEnum.MYD.getValue().equals(nlsApplyInfoVo.getPrdCode())){
//						lmtPrdContVo.setAvailAmt(lmtAmt.subtract(lmtPrdContVo.getPreOccAmt()).subtract(lmtPrdContVo.getOccAmt()));
//					}
//					if(lmtPrdContVo.getAvailAmt().compareTo(lmtAmt) == 1) {
//						throw new BizException("可用额度大于授信额度");
//					}
//					num = lmtPrdContService.updateByPk(lmtPrdContVo);
					//accLoanVo.setLoanBalance(loanBalance.subtract(rpyPrinAmt));
					/*if(BaseConstant.RECOVER_2.equals(reqBraRecoverBean.getLmtRcvrTp()) ||
							loanBalance.equals(rpyPrinAmt) ) {//借据结清，更新借据状态
						accLoanVo.setAccountStatus(BaseConstant.STD_ZB_ACC_STATUS_3);//结清
					}*/
					//num = accLoanService.updateByPk(accLoanVo);
//					LmtRecoverRecordVo.setRecoverLatAmt(lmtPrdContVo.getAvailAmt()+"");
					num = lmtRecoverRecordService.insertLmtRecoverRecord(LmtRecoverRecordVo);
				}else if(BaseConstant.RECOVER_4.equals(reqBraRecoverBean.getLmtRcvrTp()) || 
						BaseConstant.RECOVER_3.equals(reqBraRecoverBean.getLmtRcvrTp())) {//银行退票 放款失败
					if(!BaseConstant.DN_STS_0.equals(nlsApplyInfoVo.getDnSts())) {//网贷系统状态不为放款失败则做处理
						/*if(BaseConstant.DN_STS_3.equals(nlsApplyInfoVo.getDnSts())) {//待放款-----放款失败
							//预占用额度=上一次预占用额度-本次支用申请金额
							lmtPrdContVo.setPreOccAmt(preOccAmt.subtract(applyAmt));
							//已用额度=上一次已用额度
							lmtPrdContVo.setOccAmt(occAmt);
							//可用金额=授信额度-预占用额度-已用额度
							lmtPrdContVo.setAvailAmt(lmtAmt.subtract(lmtPrdContVo.getPreOccAmt()).subtract(lmtPrdContVo.getOccAmt()));
						}else {//放款成功-----放款失败
							//预占用额度=上次预占用
							lmtPrdContVo.setPreOccAmt(preOccAmt);
							//已用额度=上次已用-本次支用申请金额
							lmtPrdContVo.setOccAmt(occAmt.subtract(applyAmt));
							//可用金额=授信金额-预占用金额-已用金额
							lmtPrdContVo.setAvailAmt(lmtAmt.subtract(lmtPrdContVo.getPreOccAmt()).subtract(lmtPrdContVo.getOccAmt()));
						}
						if(lmtPrdContVo.getAvailAmt().compareTo(lmtAmt) == 1) {
							throw new BizException("可用额度大于授信额度");
						}*/
						/*int day = DateUtility.compareToDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()),lmtPrdContVo.getExpireDate());
						//尊享贷  额度在有效期内，则更新额度状态为“有效”，可用额度置为授信额度；
						if(NlsProdCdEnum.ZXD.getValue().equals(nlsApplyInfoVo.getPrdCode()) && day <= 0){
							logger.info("尊享贷额度在有效期内，更新额度状态为“有效”，可用额度置为授信额度!");
							lmtPrdContVo.setLmtStatus(ConsoleConstant.LIMIT_STS_02);
							lmtPrdContVo.setAvailAmt(lmtAmt);
						}*/
						//更新借据状态为"已冲正",更新放款状态为"失败" 恢复额度
						nlsApplyInfoVo.setDnSts(BaseConstant.DN_STS_0);//失败
						// accLoanVo.setAccountStatus(BaseConstant.STD_ZB_ACC_STATUS_2);//冲正
						num = nlsApplyInfoService.updateByPk(nlsApplyInfoVo);
						// num = accLoanService.updateByPk(accLoanVo);
//						num = lmtPrdContService.updateByPk(lmtPrdContVo);
//						LmtRecoverRecordVo.setRecoverLatAmt(lmtPrdContVo.getAvailAmt()+""); //更新恢复后的可用额度
						num = lmtRecoverRecordService.insertLmtRecoverRecord(LmtRecoverRecordVo);
					}
				}
				if(num == -1) {
					throw new BizException("数据库操作异常!");
				}
				return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean, //
						JSON.toJSONString(buildRespCreditBean(EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(), "额度恢复处理成功")), //
						EsbSysHeadEnums.RetStEnum.SUCCESS.getCode(), //
						EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(), //
						"处理成功");
			}
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean, //
					JSON.toJSONString(buildRespCreditBean(EsbBizEnums.RetCodeEnum.YWLJCLYC.getVALUE(), "非百度渠道")), //
					EsbSysHeadEnums.RetStEnum.FAILURE.getCode(), //
					EsbBizEnums.RetCodeEnum.YWLJCLYC.getVALUE(), //
					"非百度渠道");
		} catch (Exception e) {
			logger.error("额度恢复服务接口处理失败!" + e.getMessage());
			e.printStackTrace();
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean, //
					JSON.toJSONString(buildRespCreditBean(EsbBizEnums.RetCodeEnum.OTHERS_EXCEPTION.getVALUE(), e.getMessage())), //
					EsbSysHeadEnums.RetStEnum.FAILURE.getCode(), //
					EsbBizEnums.RetCodeEnum.OTHERS_EXCEPTION.getVALUE(), //
					e.getMessage());
		} finally {
			logger.info("额度恢复结束----------查询流水号：" + applySeq + "------------全局流水号" + glblSrlNo);
			TraceUtil.clear();
		}
	}

	/**
	 * 组织用户借款请求接口的返回对象
	 * 
	 * @param retStCd
	 *            返回状态码
	 * @param retMsg
	 *            返回信息
	 * @return
	 * @author huangwb
	 * @since 2019年1月20日 下午1:59:46
	 * @version 1.0
	 */
	private RespBraRecoverBean buildRespCreditBean(String retCd, String retMsg) {
		RespBraRecoverBean respBraRecoverBean = new RespBraRecoverBean();
		respBraRecoverBean.setRetCd(retCd);
		respBraRecoverBean.setRetMsg(retMsg);
		return respBraRecoverBean;
	}

	@Autowired
	@Qualifier("nlsApplyInfoService")
	private NlsApplyInfoService nlsApplyInfoService;
	@Autowired
	@Qualifier("accLoanService")
	private AccLoanService accLoanService;
	@Autowired
	@Qualifier("lmtPrdContService")
	private LmtPrdContService lmtPrdContService;
	@Autowired
	@Qualifier("lmtRecoverRecordService")
	private LmtRecoverRecordService lmtRecoverRecordService;
}
